﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace BinarySplitter
{
    public class FileBinarySplitter
    {
        private FileInfo file;

        public FileInfo File
        {
            get { return this.file; }
            set { this.file = value; }
        }

        public FileBinarySplitter(string filePath)
        {
            this.File = new FileInfo(filePath);
        }

        
        public void SplitFile()
        {
            byte[] buffer = new byte[1024 * 4];
            long totalToBeWrittenFile1;
            long totalToBeWrittenFile2 = this.File.Length / 2;
            if (this.File.Length % 2 == 0)
            {
                totalToBeWrittenFile1 = this.File.Length / 2;
            }
            else
            {
                totalToBeWrittenFile1 = (this.File.Length / 2) + 1;
            }
            using (FileStream fileStreamRead = new FileStream(this.File.FullName, FileMode.Open, FileAccess.Read),
                fileStreamToWrite1 = new FileStream(this.File.Name + @".part1", FileMode.Create, FileAccess.Write),
                fileStreamToWrite2 = new FileStream(this.File.Name + @".part2", FileMode.Create, FileAccess.Write))
            {
                BinaryReader reader = new BinaryReader(fileStreamRead);
                using (reader)
                {
                    using (BinaryWriter writer1 = new BinaryWriter(fileStreamToWrite1),
                        writer2 = new BinaryWriter(fileStreamToWrite2))
                    {
                        this.ReadAndWrite(reader, writer1, totalToBeWrittenFile1, buffer);
                        this.ReadAndWrite(reader, writer2, totalToBeWrittenFile2, buffer);
                    }
                }
            }
        }

        public void MergeTwoFiles(string fileName1, string fileName2)
        {
            FileInfo file1 = new FileInfo(fileName1);
            FileInfo file2 = new FileInfo(fileName2);
            long totalToBeReadFile1 = file1.Length;
            long totalToBeReadFile2 = file2.Length;
            byte[] buffer = new byte[1024 * 4];
            using (FileStream fileStreamWrite = new FileStream("Merged", FileMode.Create, FileAccess.Write),
                fileStreamToRead1 = new FileStream(file1.FullName, FileMode.Open, FileAccess.Read),
                fileStreamToRead2 = new FileStream(file2.FullName, FileMode.Open, FileAccess.Read))
            {
                BinaryWriter writer = new BinaryWriter(fileStreamWrite);
                using (writer)
                {
                    using (BinaryReader reader1 = new BinaryReader(fileStreamToRead1),
                        reader2 = new BinaryReader(fileStreamToRead2))
                    {
                        this.ReadAndWrite(reader1, writer, totalToBeReadFile1, buffer);
                        this.ReadAndWrite(reader2, writer, totalToBeReadFile2, buffer);
                    }
                }
            }
        }

        private void ReadAndWrite(BinaryReader readingStream, BinaryWriter writingStream, long toBeRead, byte[] buffer)
        {
            long totalRead = 0;
            int read = 0;
            long left = toBeRead - totalRead;
            while (left > buffer.Length)
            {
                read = readingStream.Read(buffer, 0, buffer.Length);
                writingStream.Write(buffer, 0, buffer.Length);
                totalRead += read;
                left = toBeRead - totalRead;
            }
            read = readingStream.Read(buffer, 0, (int)left);
            writingStream.Write(buffer, 0, (int)left);
        }
    }
}
